package thread;

import java.util.LinkedList;

/**
 * CreateBy: <a href="wangjunneil@gmail.com">Calvin</a>
 * CreateTime: 2014-05-11 14:23
 */
public class NetworkThreadPool extends ThreadGroup {

    private boolean isClosed = false;   // 线程池是否关闭
    private LinkedList<Runnable> workQueue; // 工作队列
    private static int threadPoolId;    // 线程池ID
    private int threadId;   // 工作线程ID

    public NetworkThreadPool(int poolSize) {
        super("ThreadPool-" + (threadPoolId++));
        setDaemon(true);
        workQueue = new LinkedList<Runnable>();
        for (int i = 0; i < poolSize; i++) {
            new WorkThread().start();
        }
    }

    public synchronized void execute(Runnable task) {
        if (isClosed) throw new IllegalStateException();
        if (task != null) {
            workQueue.addLast(task);
            notify();   // 唤醒正在getTask()中等待任务的工作线程
        }
    }

    protected synchronized Runnable getTask() throws InterruptedException {
        while (workQueue.size() == 0) {
            if (isClosed) return null;
            wait(); // 若工作队列中没有任务则继续等待
        }

        return workQueue.removeFirst();
    }

    public synchronized void close() {
        if (!isClosed) {
            isClosed = true;
            workQueue.clear();
            interrupt();    // 中断所有工作线程，该方法继承ThreadGroup
        }
    }

    /* 等待工作线程把所有任务执行完 */
    public void join() {
        synchronized (this) {
           isClosed = true;
           notifyAll(); // 唤醒还在getTask()中等待任务的工作线程
        }

        Thread[] threads = new Thread[activeCount()];
        int count = enumerate(threads); // enumerate方法继续ThreadGroup，获取当前所有活着的线程
        for (int i = 0; i < count; i++) {
            try {
                threads[i].join();  // 等待所有工作线程运行结束
            } catch (InterruptedException e) { }
        }
    }

    public class WorkThread extends Thread {

        public WorkThread() {
            // 加入到ThreadPool线程组中
            super(NetworkThreadPool.this, "WorkThread-" + (threadId++));
        }

        @Override
        public void run() {
            while (!isInterrupted()) {
                Runnable task = null;
                try {
                    task = getTask();
                } catch (InterruptedException e) { }

                /* 若getTask()返回null或者线程执行getTask()时被中断，则结束此线程 */
                if (task == null) return;

                try {
                    task.run();
                } catch (Throwable th) {
                    th.printStackTrace();
                }
            }
        }
    }

}
